package org.yscz.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.yscz.common.Constants;
import org.yscz.common.HttpStatus;
import org.yscz.common.Result;
import org.yscz.entity.Testee;
import org.yscz.entity.TesteeGroup;
import org.yscz.entity.User;
import org.yscz.entity.vo.TesteeVo;
import org.yscz.mqtt.MqttCustomClient;
import org.yscz.mqtt.PubCallBack;
import org.yscz.service.TesteeService;
import org.yscz.service.UserService;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 被测人接口
 *
 * @author muqs
 * @create 2021-08-22 18:45
 */
@RestController
@Slf4j
@Api("被测人接口")
public class TesteeController {
    @Autowired
    private UserService userService;

    @Autowired
    private TesteeService testeeService;

    @Autowired
    private MqttCustomClient mqttCustomClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 新增被测人接口
     *
     * @param testeeVo 前台传递的被测人数据
     * @return Result对象
     */
    @PostMapping("/testee/add")
    @ApiOperation(value = "新增被测人接口", httpMethod = "POST")
    public Result add(@RequestBody TesteeVo testeeVo) {
        log.info("testeeVo:[{}]", testeeVo);
        //notifyAlg(testeeVo.getTesteeName());
        //从redis取出imageKey对应的通知算法的信息
        String imageJson = stringRedisTemplate.opsForValue().get(PicturesUploadController.imageKey);
        //JSONObject jsonObject = JSONObject.parseObject(imageJson);
        //通知算法是被测人
        //role：0-测评人 1-被测人
        //jsonObject.put("role", 1);
        //通知算法入人脸库
        mqttCustomClient.publish(Constants.IMAGE_QUALITY_CONTROL_AGAIN, imageJson);
        //根据算法返回的结果去判断是否要新增被测人
        JSONObject jsonObject = PubCallBack.imageQualityResultMsg;
        //have_face
        Boolean haveFace = (Boolean) jsonObject.get(Constants.HAVE_FACE);
        //quality
        Boolean quality = (Boolean) jsonObject.get(Constants.QUALITY);
        //library_have
        Boolean libraryFace = (Boolean) jsonObject.get(Constants.LIBRARY_HAVE);
        if (haveFace && quality && !libraryFace) {
            testeeService.add(testeeVo);
            return Result.success(HttpStatus.SUCCESS, "新增被测人成功", testeeVo);
        } else if (!haveFace) {
            return Result.success(HttpStatus.SUCCESS, "该照片未检测到人脸");
        } else if (!quality) {
            return Result.success(HttpStatus.SUCCESS, "检测到人脸但人脸清晰度不合格");
        } else if (libraryFace) {
            return Result.success(HttpStatus.SUCCESS, "库中已经存在该人信息,不需要新增");
        }
        return null;
    }

    /**
     * 通知算法入人脸库
     */
    public void notifyAlg(String name) {
        //根据用户名去被测人查询
        QueryWrapper<Testee> testeeQueryWrapper = new QueryWrapper<>();
        testeeQueryWrapper.eq("testee_name", name);
        Testee testee = testeeService.getOne(testeeQueryWrapper);

        //根据用户名去账号中查询
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("user_name", name);
        User user = userService.getOne(userQueryWrapper);

        //从redis取出imageKey对应的通知算法的信息
        String imageJson = stringRedisTemplate.opsForValue().get(PicturesUploadController.imageKey);
        JSONObject jsonObject = JSONObject.parseObject(imageJson);

        //oldRole：0-两个表都没有 1-测评人有，被测人没有 2-测评人没有，被测人有 3-两张表都有
        //newRole：0-测评人 1-被测人
        //测评人和被侧人数据库都没有此条记录
        if (null == testee && null == user) {
            jsonObject.put("oldRole", 0);
        } else if (null == testee && null != user) { //测评人有，被测人没有
            jsonObject.put("oldRole", 1);
        } else if (null != testee && null == user) { //测评人没有，被测人有
            jsonObject.put("oldRole", 2);
        } else if (null != testee && null != user) { //测评人和被侧人数据库都有此条记录
            jsonObject.put("oldRole", 3);
        }
        jsonObject.put("newRole", 1);

        //通知算法入人脸库
        mqttCustomClient.publish(Constants.IMAGE_QUALITY_CONTROL_AGAIN, JSONObject.toJSONString(jsonObject));
    }

    /**
     * 修改被测人接口
     *
     * @param testeeVo 前台传递的被测人数据
     * @return Result对象
     */
    @PostMapping("/testee/modify")
    @ApiOperation(value = "修改被测人接口", httpMethod = "POST")
    public Result modify(@RequestBody TesteeVo testeeVo) {
        log.info("testeeVo:[{}]", testeeVo);
        testeeService.modify(testeeVo);
        return Result.success(HttpStatus.SUCCESS, "修改被测人成功", "");
    }

    /**
     * 删除被测人接口
     *
     * @param testeeId 前台传递的被测人ID
     * @return Result对象
     */
    @DeleteMapping("/testee/del/{testeeId}")
    @ApiOperation(value = "删除被测人接口", httpMethod = "DELETE")
    public Result del(@PathVariable Long testeeId) {
        log.info("testeeId:[{}]", testeeId);
        testeeService.del(testeeId);
        return Result.success(HttpStatus.SUCCESS, "删除被测人成功", "");
    }

    /**
     * 查询被测人列表接口
     *
     * @param testeeName      被测人姓名
     * @param sex             性别
     * @param testeeGroupIdFk 班级
     * @param pageNum         当前页
     * @param pageSize        每页数据条数
     * @return Result对象
     */
    @GetMapping("/testee/listPage")
    @ApiOperation(value = "查询被测人列表接口", httpMethod = "GET")
    public Result list(@RequestParam(value = "testeeName", required = false) String testeeName,
                       @RequestParam(value = "sex", required = false) Integer sex,
                       @RequestParam(value = "testeeGroupIdFk", required = false) Long testeeGroupIdFk,
                       @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                       @RequestParam(value = "pageSize", required = false, defaultValue = "6") Integer pageSize) {
        JSONObject reusltObj = new JSONObject();
        IPage<TesteeVo> page = new Page(pageNum, pageSize);
        Map condition = new HashMap<>();

        if (!StringUtils.isEmpty(testeeName)) {
            condition.put("testeeName", "%" + testeeName.replaceAll(" ", "") + "%");
        }

        if (sex != null) {
            condition.put("sex", sex);
        }

        if (testeeGroupIdFk != null) {
            condition.put("testeeGroupIdFk", testeeGroupIdFk);
        }

        IPage<TesteeVo> testeeVoIPage = testeeService.listPageByCondition(page, condition);

        reusltObj.put("list", testeeVoIPage == null ? new ArrayList<>() : testeeVoIPage.getRecords());
        reusltObj.put("total", testeeVoIPage == null ? 0 : testeeVoIPage.getTotal());

        return Result.success(HttpStatus.SUCCESS, "查询被测人列表成功", reusltObj);
    }

    /**
     * 查询班级列表接口
     *
     * @return Result对象
     */
    @GetMapping("/testeeGroup/list")
    @ApiOperation(value = "查询班级列表接口", httpMethod = "GET")
    public Result testeeGroup() {
        List<TesteeGroup> testeeGroupList = testeeService.queryTesteeGroup();
        return Result.success(HttpStatus.SUCCESS, "查询班级列表成功", testeeGroupList);
    }

    /**
     * 查询被测人详情接口
     *
     * @return Result对象
     */
    @GetMapping("/testee/detail/{testeeId}")
    @ApiOperation(value = "查询被测人详情接口", httpMethod = "GET")
    public Result testeeDetail(@PathVariable Long testeeId) {
        TesteeVo testeeVo = testeeService.testeeDetail(testeeId);
        return Result.success(HttpStatus.SUCCESS, "查询被测人详情成功", testeeVo);
    }

    /**
     * 手动选择被测人
     *
     * @return Result对象
     */
    @GetMapping("/testee/manualSelect")
    @ApiOperation(value = "手动选择被测人接口", httpMethod = "GET")
    public Result downloadTemp(@RequestParam(value = "searchText", required = false) String searchText,
                               @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                               @RequestParam(value = "pageSize", required = false, defaultValue = "8") Integer pageSize) {

        JSONObject reusltObj = new JSONObject();
        IPage<TesteeVo> page = new Page(pageNum, pageSize);
        Map condition = new HashMap();
        if (!StringUtils.isEmpty(searchText)) {
            condition.put("searchText", "%" + searchText.replace(" ", "") + "%");
        }
        IPage<TesteeVo> testeeVoIPage = testeeService.manualSelect(page, condition);

        reusltObj.put("list", testeeVoIPage == null ? new ArrayList<>() : testeeVoIPage.getRecords());
        reusltObj.put("total", testeeVoIPage == null ? 0 : testeeVoIPage.getTotal());

        return Result.success(HttpStatus.SUCCESS, "查询被测人成功", reusltObj);
    }

    /**
     * 下载导入模板
     *
     * @return Result对象
     */
    @GetMapping("/testee/downloadTemp")
    @ApiOperation(value = "下载导入模板接口", httpMethod = "GET")
    public void downloadTemp(HttpServletRequest request, HttpServletResponse response) {
        Workbook workbook;
        String filename = "testee";
        ClassPathResource resource = new ClassPathResource("/templates/" + filename + ".xlsx");
        try {
            InputStream inputStream = resource.getInputStream();
            workbook = WorkbookFactory.create(inputStream);
            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("mutipart/form-data");
            if (workbook.getClass().getSimpleName() == "HSSFWorkbook") {
                response.setHeader("Content-Disposition", "attachment; filename=" + new String(filename.getBytes(), "UTF-8") + ".xls");
            } else {
                response.setHeader("Content-Disposition", "attachment; filename=" + new String(filename.getBytes(), "UTF-8") + ".xlsx");
            }
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            log.error("下载被测人导入模板异常,errorL{}", e);
        }
    }

    /**
     * 批量导入
     *
     * @return Result对象
     */
    @PostMapping("/testee/importExcel")
    @ApiOperation(value = "被测人批量导入接口", httpMethod = "POST")
    public Result downloadTemp(@RequestParam(value = "file") MultipartFile multipartFile) {

        if (multipartFile == null) {
            return Result.error(HttpStatus.BAD_REQUEST, "请选择上传文件");
        }
        testeeService.importExcel(multipartFile);

        return Result.success(HttpStatus.SUCCESS, "被测人批量导入成功", "");
    }
}
